/*
 * FSWUniCEUB - 2008
 * 
 * Este arquivo é de propriedade da Fábrica de Software do UniCEUB
 * 
 * Para mais informações entre em contato com a coordenação do
 * curso de Ciência da Computação da instituição.
 */

package br.uniceub.fsw.indicadores.dao;

import br.uniceub.fsw.arquitetura.persistencia.dao.BaseDAO;
import br.uniceub.fsw.arquitetura.persistencia.dao.ConstrutorSQL;
import br.uniceub.fsw.indicadores.vo.IndicadorVO;
import br.uniceub.fsw.indicadores.vo.PlanoMedicaoVO;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * Data Access Object da entidade Indicador. Essa classe é responsável por todas as 
 * operações de banco de dados relacionadas à entidade.
 * 
 * @author Marcos Mello Nobrega Soares ra20136178
 */
public class IndicadorDAO extends BaseDAO<IndicadorVO> {

    @Override
    public void inserir(IndicadorVO entidade) {

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("INSERT INTO TB_Indicador(NO_Indicador, DS_Indicador,");
        query.append("DS_MetaIndicador, VL_MetaIndicador,");
        query.append("VL_LimiteControleSuperior, VL_LimiteControleInferior,");
        query.append("CD_Periodicidade,");
        query.append("DT_InicioCalculoIndicador, DT_UltimoCalculoIndicador,");
        query.append("DT_Validade, DT_Criacao,");
        query.append("DS_FormulaIndicador, NO_ProcedimentoCalculoIndicador,");
        query.append("DS_UnidadeMedidaIndicador,");
        query.append("ST_IndicadorManual, ST_IndicadorAtivo, CD_Dimensao)");
        query.append("VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

        List<?> parametros = criarParametros(entidade.getNoIndicador(), entidade.getDsIndicador(),
                entidade.getDsMetaIndicador(), entidade.getVlMetaIndicador(),
                entidade.getVlLimiteControleSuperior(), entidade.getVlLimiteControleInferior(),
                entidade.getCdPeriodicidade(),
                entidade.getDtInicioCalculoIndicador(), entidade.getDtUltimoCalculoIndicador(),
                entidade.getDtValidade(), entidade.getDtCriacao(),
                entidade.getDsFormulaIndicador(), entidade.getNoProcedimentoCalculoIndicador(),
                entidade.getDsUnidadeMedidaIndicador(),
                entidade.getStIndicadorManual(), entidade.getStIndicadorAtivo(), entidade.getCdDimensao());

        Integer idGerado = ((Long) executarInsercao(query.toString(), parametros)).intValue();

        entidade.setIdIndicador(idGerado);
    }

    @Override
    public void alterar(IndicadorVO entidade) {

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("UPDATE TB_Indicador SET NO_Indicador = ?, DS_Indicador = ?,");
        query.append("DS_MetaIndicador = ?, VL_MetaIndicador = ?,");
        query.append("VL_LimiteControleSuperior = ?, VL_LimiteControleInferior = ?,");
        query.append("CD_Periodicidade = ?,");
        query.append("DT_InicioCalculoIndicador = ?, DT_UltimoCalculoIndicador = ?,");
        query.append("DT_Validade = ?,");
        query.append("DS_FormulaIndicador = ?, NO_ProcedimentoCalculoIndicador = ?,");
        query.append("DS_UnidadeMedidaIndicador= ?,");
        query.append("ST_IndicadorManual = ?, ST_IndicadorAtivo = ?,");
        query.append("CD_Dimensao = ?");
        query.append("WHERE ID_Indicador = ?");

        List<?> parametros = criarParametros(entidade.getNoIndicador(), entidade.getDsIndicador(),
                entidade.getDsIndicador(), entidade.getVlMetaIndicador(), 
                entidade.getVlLimiteControleSuperior(), entidade.getVlLimiteControleInferior(),
                entidade.getCdPeriodicidade(),
                entidade.getDtInicioCalculoIndicador(), entidade.getDtUltimoCalculoIndicador(),
                entidade.getDtValidade(),
                entidade.getDsFormulaIndicador(), entidade.getNoProcedimentoCalculoIndicador(), 
                entidade.getDsUnidadeMedidaIndicador(),
                entidade.getStIndicadorManual(), entidade.getStIndicadorAtivo(),
                entidade.getCdDimensao(), entidade.getIdIndicador());

        executarAlteracao(query.toString(), parametros);
    }

    @Override
    public void excluir(IndicadorVO entidade) {

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("DELETE FROM TB_Indicador");
        query.append("WHERE ID_Indicador = ?");

        executarAlteracao(query.toString(), criarParametros(entidade.getIdIndicador()));
    }

    @Override
    public IndicadorVO consultarPorId(Serializable id) {

        IndicadorVO entidade = null;

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("SELECT * FROM TB_Indicador T WHERE T.ID_Indicador = ?");

        entidade = consultarUm(query.toString(), criarParametros(id));

        return entidade;
    }

    @Override
    public List<IndicadorVO> consultarPorExemplo(IndicadorVO exemplo) {

        List<IndicadorVO> listaRetorno = null;

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("SELECT * FROM TB_Indicador T WHERE 1=1");

        mapearQueryParaExemplo(query, exemplo);

        listaRetorno = consultar(query.toString(), recuperarParametros());

        return listaRetorno;
    }
    
    /**
     * Procura indicadores cujo o id seja igual ao argumento ou nome contenha o argumento.
     * Filtra os outros atributos pelo objeto de exemplo.
     * 
     * @param exemplo de indicador para filtragem
     * @param argumento de pesquisa
     * @return
     */
    public List<IndicadorVO> consultarPorExemploNomeOuId(IndicadorVO exemplo, String argumento) {
        
        Integer id;
        
        try {
            id = Integer.valueOf(argumento);  
            
            List<IndicadorVO> listaRetorno = null;

            ConstrutorSQL query = new ConstrutorSQL();

            query.append("SELECT * FROM TB_Indicador T WHERE 1=1");

            exemplo.setIdIndicador(null);
            exemplo.setNoIndicador(null);
            
            mapearQueryParaExemplo(query, exemplo);
            
            adicionarParametro("%" + argumento + "%");
            adicionarParametro(id);

            query.append("AND (NO_Indicador LIKE ? OR ID_Indicador = ?)");
            
            listaRetorno = consultar(query.toString(), recuperarParametros());

            return listaRetorno;
        }
        catch (NumberFormatException e) {
            
            exemplo.setNoIndicador(argumento);
            return consultarPorExemplo(exemplo);
        }        
    }
    
    /**
     * Retorna a lista de Indicadores associados a dado plano de medição.
     * 
     * @param plano de medição
     * @param exemplo de indicador para outras filtragens
     * @return
     */
    public List<IndicadorVO> consultarPorPlanoMedicao(PlanoMedicaoVO plano, IndicadorVO exemplo) {

        List<IndicadorVO> listaRetorno = null;

        if(plano != null) {
            ConstrutorSQL query = new ConstrutorSQL();

            query.append("" +
                    "SELECT " +
                    "   DISTINCT T.* " +
                    "FROM " +
                    "   TB_Indicador T" +
                    "       INNER JOIN TA_ObjetivoIndicador OI " +
                    "           ON  OI.CD_Indicador = T.ID_Indicador " +
                    "       INNER JOIN TA_PlanoMedicaoObjetivo PO " +
                    "           ON PO.CD_Objetivo = OI.CD_Objetivo " +
                    "       INNER JOIN TB_Objetivo O" +
                    "           ON O.ID_Objetivo = OI.CD_Objetivo " +
                    "WHERE " +
                    "   O.ST_ObjetivoAtivo = 'S' AND PO.CD_PlanoMedicao = ?  ");
            
            adicionarParametro(plano.getIdPlanoMedicao());

            if(exemplo != null)
                mapearQueryParaExemplo(query, exemplo);

            listaRetorno = consultar(query.toString(), recuperarParametros());
        }
        
        return listaRetorno;
    }
    
    
    
    /**
     * Retorna a lista de Indicadores que possuem valores registrados.
     * 
     * @param valor indicador
     * @param exemplo de indicador para outras filtragens
     * @return
     */
    public List<IndicadorVO> consultarIndicadoresComValor(IndicadorVO exemplo) {

        List<IndicadorVO> listaRetorno = null;

        ConstrutorSQL query = new ConstrutorSQL();

        query.append("" +
                    "SELECT DISTINCT " +
                    "   T.* " +
                    "FROM " +
                    "   TB_Indicador T" +
                    "       INNER JOIN TB_ValorIndicador VI " +
                    "           ON  VI.CD_Indicador = T.ID_Indicador " +
                    "WHERE 1=1 ");
            
        if(exemplo != null)
            mapearQueryParaExemplo(query, exemplo);

        listaRetorno = consultar(query.toString(), recuperarParametros());
        
        return listaRetorno;
    }
    
    /**
     * Retorna a lista de Indicadores associados a dado plano de medição.
     * 
     * @param plano de medição
     * @return
     */
    public List<IndicadorVO> consultarPorPlanoMedicao(PlanoMedicaoVO plano) {
        return consultarPorPlanoMedicao(plano, null);
    }

    @Override
    protected IndicadorVO extrairObjetoResultado(ResultSet rs) throws SQLException {

        IndicadorVO entidade = new IndicadorVO();
        
        entidade.setIdIndicador(new Integer(rs.getInt("ID_Indicador")));        
        entidade.setNoIndicador(rs.getString("NO_Indicador"));
        entidade.setDsIndicador(rs.getString("DS_Indicador"));
        entidade.setDsMetaIndicador(rs.getString("DS_MetaIndicador"));
        entidade.setVlMetaIndicador(new Float(rs.getFloat("VL_MetaIndicador")));
        entidade.setVlLimiteControleSuperior(new Float(rs.getFloat("VL_LimiteControleSuperior")));
        entidade.setVlLimiteControleInferior(new Float(rs.getFloat("VL_LimiteControleInferior")));
        entidade.setCdPeriodicidade(new Integer(rs.getInt("CD_Periodicidade")));
        entidade.setDtInicioCalculoIndicador(rs.getDate("DT_InicioCalculoIndicador"));
        entidade.setDtUltimoCalculoIndicador(rs.getDate("DT_UltimoCalculoIndicador"));
        entidade.setDtValidade(rs.getDate("DT_Validade"));
        entidade.setDtCriacao(rs.getDate("DT_Criacao"));
        entidade.setDsFormulaIndicador(rs.getString("DS_FormulaIndicador"));
        entidade.setNoProcedimentoCalculoIndicador(rs.getString("NO_ProcedimentoCalculoIndicador"));
        entidade.setDsUnidadeMedidaIndicador(rs.getString("DS_UnidadeMedidaIndicador"));
        entidade.setStIndicadorManual(rs.getString("ST_IndicadorManual"));
        entidade.setStIndicadorAtivo(rs.getString("ST_IndicadorAtivo"));
        entidade.setCdDimensao(new Integer(rs.getInt("CD_Dimensao")));

        return entidade;
    }

    @Override
    protected void mapearQueryParaExemplo(ConstrutorSQL query, IndicadorVO exemplo) {

        if (exemplo.getNoIndicador() != null && !exemplo.getNoIndicador().isEmpty()) {
            query.append("AND T.NO_Indicador LIKE ?");
            adicionarParametro("%" + exemplo.getNoIndicador() + "%");
        }

        if (exemplo.getDsIndicador() != null && !exemplo.getDsIndicador().isEmpty()) {
            query.append("AND T.DS_Indicador LIKE ?");
            adicionarParametro("%" + exemplo.getDsIndicador() + "%");
        }
        
        if (exemplo.getDsMetaIndicador() != null && !exemplo.getDsMetaIndicador().isEmpty()) {
            query.append("AND T.DS_MetaIndicador LIKE ?");
            adicionarParametro("%" + exemplo.getDsMetaIndicador() + "%");
        }
        
        if (exemplo.getVlMetaIndicador() != null) {
            query.append("AND T.VL_MetaIndicador = ?");
            adicionarParametro(exemplo.getVlMetaIndicador());
        }
        
        if (exemplo.getVlLimiteControleSuperior() != null) {
            query.append("AND T.VL_LimiteControleSuperior = ?");
            adicionarParametro(exemplo.getVlLimiteControleSuperior());
        }
        
        if (exemplo.getVlLimiteControleInferior() != null) {
            query.append("AND T.VL_LimiteControleInferior = ?");
            adicionarParametro(exemplo.getVlLimiteControleInferior());
        }
        
        if (exemplo.getCdPeriodicidade() != null) {
            query.append("AND T.CD_Periodicidade = ?");
            adicionarParametro(exemplo.getCdPeriodicidade());
        }
        
        if (exemplo.getDtInicioCalculoIndicador() != null) {
            query.append("AND T.DT_InicioCalculoIndicador = ?");
            adicionarParametro(exemplo.getDtInicioCalculoIndicador());
        }
        
        if (exemplo.getDtUltimoCalculoIndicador() != null) {
            query.append("AND T.DT_UltimoCalculoIndicador = ?");
            adicionarParametro(exemplo.getDtUltimoCalculoIndicador());
        }
        
        if (exemplo.getDtValidade() != null) {
            query.append("AND T.DT_Validade = ?");
            adicionarParametro(exemplo.getDtValidade());
        }
        
        if (exemplo.getDtCriacao() != null) {
            query.append("AND T.DT_Criacao = ?");
            adicionarParametro(exemplo.getDtCriacao());
        }
        
        if (exemplo.getDsFormulaIndicador() != null) {
            query.append("AND T.DS_FormulaIndicador = ?");
            adicionarParametro(exemplo.getDsFormulaIndicador());
        }
        
        if (exemplo.getNoProcedimentoCalculoIndicador() != null) {
            query.append("AND T.NO_ProcedimentoCalculoIndicador = ?");
            adicionarParametro(exemplo.getNoProcedimentoCalculoIndicador());
        }
        
        if (exemplo.getDsUnidadeMedidaIndicador() != null) {
            query.append("AND T.DS_UnidadeMedidaIndicador = ?");
            adicionarParametro(exemplo.getDsUnidadeMedidaIndicador());
        }
        
        if (exemplo.getStIndicadorManual() != null) {
            query.append("AND T.ST_IndicadorManual = ?");
            adicionarParametro(exemplo.getStIndicadorManual());
        }
        
        if (exemplo.getStIndicadorAtivo() != null) {
            query.append("AND T.ST_IndicadorAtivo = ?");
            adicionarParametro(exemplo.getStIndicadorAtivo());
        }
        
        if (exemplo.getCdDimensao() != null) {
            query.append("AND T.CD_Dimensao = ?");
            adicionarParametro(exemplo.getCdDimensao());
        }
    }
}
